package com.gy.boot.controller;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.compress.ZipWriter;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.gy.boot.common.aspect.Permissions;
import com.gy.boot.common.dao.IDao;
import com.gy.boot.common.dao.IEntity;
import com.gy.boot.common.dao.IPage;
import com.gy.boot.common.dao.IPageHelp;
import com.gy.boot.common.dao.SqlID;
import com.gy.boot.common.exception.SysException;
import com.gy.boot.common.socket.WebSocketServer;
import com.gy.boot.common.util.DateTool;
import com.gy.boot.common.util.R;
import com.gy.boot.common.util.UploadUtil;
import com.gy.boot.other.LxyExcel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ExecutorService;

@RestController
@RequestMapping("test")
public class TestController extends BaseController {

    @Autowired
    IDao<Map<String,Object>> iDao;

    @Autowired
    private WebSocketServer webSocketServer;

    @RequestMapping()
    public Object index() {
        return "<h1>欢迎 访问 我们的 项目 boot-demo </h1>";
    }


    @RequestMapping("list")
    public Object testList() {
//        IPageHelp.start(1, 5);
        IEntity params = IEntity.create(2).set("user_id", 1).set("test_id", 1)
                .set("listId", new int[]{1, 1, 2, 2, 3, 3});
        List<Map<String, Object>> list = iDao.list(SqlID.User_listUserEntity, params);
        System.out.println(list);
        return list;
    }

    /**
     * 系统指定发送消息
     * */
    @GetMapping("sendSocketMsg")
    public Object sendSocketMsg(String id, String msg) {
        webSocketServer.sendMsg(id, msg);
        return R.ok();
    }

    /**
     * 发送广播
     * */
    @GetMapping("sendRadio")
    public Object sendRadio(String msg) {
        webSocketServer.sendRadio(msg);
        return R.ok();
    }


    private static final ThreadLocal<String> T_L = new ThreadLocal<>();

    @GetMapping("TL")
    public Object testTL(String tl) throws InterruptedException {
        System.out.println(tl);
        T_L.set(tl);

        Thread.sleep(10000);

        String tl2 = T_L.get();
        System.out.println(tl2);

        return tl2;
    }


    @GetMapping("page")
    public Object testPage() {
//        IPageHelp.start(1, 10);
        IPage page1 = IPageHelp.getLocalPage();
        System.out.println("page1: " + page1);
        return page1;
    }

    @GetMapping("map")
    public R testMap(@RequestParam Map<String, Object> params) {
        return R.ok().setAll(params);
    }

    @PostMapping("map")
    public R testMap2(@RequestParam Map<String, Object> params) {
        return R.ok().setAll(params);
    }

    @Permissions
    @GetMapping("permissions")
    public R permissions() {
        return R.ok();
    }

    @Permissions()
    @GetMapping("permissions1")
    public R permissions1() {
        return R.ok();
    }

    @Permissions()
    @GetMapping("permissions2")
    public R permissions2() {
        return R.ok();
    }

    @GetMapping("listLog")
    public Object listLog() {
        return IDao.listS(SqlID.SysLog_listLog, null);
    }


    @GetMapping("path")
    public R file(HttpServletRequest request) {
        String home = System.getProperty("user.home");
        System.out.println(home);

        String dir = System.getProperty("user.dir");
        System.out.println(dir);

        R ok = R.ok();
        ok.put("home", home);
        ok.put("dir", dir);
        return ok;
    }

    @GetMapping("logs")
    public R logs() {
        String rootDir = System.getProperty("user.dir");
        String logFile = rootDir + "/logs/";

        List<String> listLogPath = FileUtil.listFileNames(logFile);
        ListUtil.reverse(listLogPath);
        System.out.println(listLogPath);

        R ok = R.ok();
        ok.put("listLogPath", listLogPath);

        return ok;
    }

    /** 下载文件: http://localhost:8083/test/download */
    @GetMapping("download")
    public void download(HttpServletResponse response) throws IOException {
        String fileName = "汤毅420703198603203379WQHT804.pdf";
        UploadUtil.download(fileUrlHttp, fileName, response);
    }

    private static final String fileUrlHttp = "http://rrkj-xchuangw.oss-cn-shanghai.aliyuncs.com/file/20240328/202403281040041-765-24032810404001087498.pdf?Expires=1712137375&OSSAccessKeyId=LTAI4G4RarSb4ibE4iW529Mi&Signature=%2FjoLesI2Vz3r9e6OLlMxaaooWXo%3D";

    /** 下载文件: http://localhost:8083/test/zip */
    @GetMapping("zip")
    public void zip(HttpServletResponse response) {
        response.reset();
        response.setCharacterEncoding("utf-8");
        response.setContentType("multipart/form-data");
        response.setContentType("application/octet-stream; charset=UTF-8");
        response.addHeader("Access-Control-Allow-Origin", "*"); // 解决跨域
        String fileName = DateTool.format(new Date(), "yyyyMMddHHmmss")+"ZipFP.zip";
        response.setHeader("Content-Disposition", "attachment;filename=\""+fileName+"\"");
        ZipWriter zipWriter = null;
        List<List<String>> listErrRows = new ArrayList<>();
        listErrRows.add(Arrays.asList("文件", "错误原因"));
        try {
            zipWriter = ZipWriter.of(response.getOutputStream(), StandardCharsets.UTF_8);
            try { // 文件1
                String path = "E:/Test/PDF/fileHttp.pdf";
                FileUtil.del(path); // 删除原文件
                File file = FileUtil.file(path);
                URL url = URLUtil.url(fileUrlHttp);
                FileUtil.writeFromStream(url.openStream(), file);
                zipWriter.add(false, null, file);
                FileUtil.del(file); // 删除文件-避免占用内存
            } catch (Exception e) {
                logger.error("文件1获取失败: ", e);
                listErrRows.add(Arrays.asList("文件1", e.getMessage()));
            }
            try { // 文件2
                String path = "E:/Test/PDF/fileFP2.pdf";
                FileUtil.del(path); // 删除原文件
                List<String> listStr = FileUtil.readUtf8Lines("E:/Test/PDF/fileFP.txt");
                byte[] decode = Base64.decode(listStr.get(0));
                File file = FileUtil.file(path);
                FileUtil.writeBytes(decode, file);
                zipWriter.add(false, null, file);
                FileUtil.del(file); // 删除文件-避免占用内存
            } catch (Exception e) {
                logger.error("文件2获取失败: ", e);
                listErrRows.add(Arrays.asList("文件2", e.getMessage()));
            }
            try { // 文件3
                File file = FileUtil.file("E:/Test/PDF/3.pdf");
                zipWriter.add(false, null, file);
            } catch (Exception e) {
                logger.error("文件3获取失败: ", e);
                listErrRows.add(Arrays.asList("文件3", e.getMessage()));
            }
            if (listErrRows.size() > 1) {
                try { // 错误文件
                    String path = "E:/Test/PDF/errMsg.xlsx";
                    ExcelWriter writer = ExcelUtil.getWriter(path, "0");
                    writer.write(listErrRows);
                    writer.close();
                    File file = FileUtil.file(path);
                    zipWriter.add(false, null, file);
                    FileUtil.del(file); // 删除文件-避免占用内存
                } catch (Exception e) {
                    logger.error("错误文件获取失败: ", e);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IoUtil.close(zipWriter);
        }
    }



    @GetMapping("intern")
    public void intern() throws InterruptedException {
        long id = 1;
        System.out.println("请求==");
        synchronized (getSynchronizedKey(id)) {
            System.out.println("开始");
            Thread.sleep(3000);
            System.out.println("结束");
        }
    }


    private static final String intern_ = "intern_";
    private static String getSynchronizedKey(long id) {
        return (intern_+id).intern();
    }




    @GetMapping("getPath")
    public String getPath(HttpServletRequest request) {
        return UploadUtil.BASE_PATH;
    }


    @GetMapping("sync")
    public synchronized Object sync() throws InterruptedException {
        Thread.sleep(10000);
        return DateUtil.date().toString();
    }

    private static final Map<String, Integer> map = new HashMap<>();
    private static final ExecutorService compareThread = ThreadUtil.newFixedExecutor(5, "测试", true);
    @GetMapping("testTh")
    public Object testTh(int i) {
        if (map.isEmpty()) { map.put("A", 0); }
//        ThreadUtil.execute(() -> testTh2("test0"));
        compareThread.execute(() -> testTh2("test1-"+i));
        compareThread.execute(() -> testTh2("test2-"+i));
        compareThread.execute(() -> testTh2("test3-"+i));
        return R.ok(map.get("A"));
    }
    private void testTh2(String remark) {
        logger.info("============= {"+remark+"-开始-"+map.get("A")+"} =========");
        synchronized ("A") { map.put("A", map.get("A")+1); }
        ThreadUtil.sleep(5000);
        logger.info("============= {"+remark+"-结束-"+map.get("A")+"} =========");
    }




    /**
     * 表格需要重新排序的文件上传页面: http://vd24878994b.vicp.fun/html/LxyExcel.html
     * 表格需要重新排序的文件上传页面: http://localhost:8083/html/LxyExcel.html
     * */
    @PostMapping("LxyExcel")
    public synchronized void LxyExcel(@RequestParam(value = "file") MultipartFile file, HttpServletResponse response) throws Exception {
        String new_path = UploadUtil.upload(file, "LXY", true);
        if (new_path == null || new_path.isEmpty()) { throw new SysException("下载文件不存在"); }
        LxyExcel.updateXH(new_path, "Sheet1"); // 处理排序
        String fileName = file.getOriginalFilename();
        UploadUtil.download(new_path, fileName, response);
    }





}
